﻿using System.Collections.Generic;

using UnityEngine;

namespace Assets.XyzCode.VisualEffect
{
    /// <summary>
    /// 命中光效工厂类
    /// </summary>
    public sealed class HitLitFactory
    {
        /** 池大小 */
        private const int POOL_SIZE = 32;

        /** 对象池 */
        static private readonly Queue<GameObject> _pool = new Queue<GameObject>(POOL_SIZE);

        /** 预制体 */
        static private GameObject GO_PREFAB;

        /// <summary>
        /// 私有化类默认构造器
        /// </summary>
        private HitLitFactory()
        {
        }

        /// <summary>
        /// 准备
        /// </summary>
        static public void Prepare()
        {
            // 异步方式加载命中光效
            ResourceRequest resReq = Resources.LoadAsync<GameObject>("VisualEffect/Prefab/HitLit");

            resReq.completed += (asyncOp) =>
            {
                GameObject goPrefab = resReq.asset as GameObject;

                if (null == goPrefab)
                {
                    Debug.LogError("预制体加载失败");
                    return;
                }

                // 提前加载一下, 避免卡帧
                GameObject goTemp = GameObject.Instantiate<GameObject>(goPrefab);
                goTemp.transform.localScale = Vector3.one * 0.001f;
                goTemp.transform.position = Vector3.down * 4096;

                GameObject.Destroy(goTemp, 1);
                GO_PREFAB = goPrefab;
            };
        }

        /// <summary>
        /// 创建命中光效
        /// </summary>
        /// <returns>Unity 游戏对象</returns>
        static public GameObject Create()
        {
            return Borrow();
        }

        /// <summary>
        /// 借出对象
        /// </summary>
        /// <returns>Unity 游戏对象</returns>
        static public GameObject Borrow()
        {
            if (null == GO_PREFAB)
            {
                return null;
            }

            GameObject goCurr = null;

            if (_pool.Count > 0)
            {
                // 如果队列里有可以借出的对象,
                // 令对象出队...
                goCurr = _pool.Dequeue();
            }
            
            if (null == goCurr)
            {
                // 如果借出对象为空, 就新建
                goCurr = GameObject.Instantiate<GameObject>(GO_PREFAB);
                goCurr.AddComponent<HitLitBehav>();
                goCurr.transform.SetParent(
                    GameObject.Find("/Game").transform
                );
            }

            // 重新激活
            goCurr.GetComponent<HitLitBehav>().ReActive();

            return goCurr;
        }

        /// <summary>
        /// 归还对象
        /// </summary>
        /// <param name="goCurr">Unity 游戏对象</param>
        static public void GiveBack(GameObject goCurr)
        {
            if (null == goCurr)
            {
                return;
            }

            // 设置为不活动状态
            goCurr.GetComponent<HitLitBehav>().DeActive();

            if (_pool.Count < POOL_SIZE)
            {
                _pool.Enqueue(goCurr);
            }
            else
            {
                GameObject.Destroy(goCurr);
            }
        }

        /// <summary>
        /// 命中光效行为
        /// </summary>
        private class HitLitBehav : MonoBehaviour
        {
            /** 存活时间 */
            private float _survivalTime;

            /// <summary>
            /// Update
            /// </summary>
            private void Update()
            {
                if (_survivalTime > 0)
                {
                    // 先等一会儿
                    _survivalTime -= Time.deltaTime;
                    return;
                }

                GiveBack(gameObject);
            }

            /// <summary>
            /// 重新激活
            /// </summary>
            public void ReActive()
            {
                _survivalTime = 0.3f;
                gameObject.SetActive(true);
                enabled = true;
            }

            /// <summary>
            /// 设置为不活动状态
            /// </summary>
            public void DeActive()
            {
                _survivalTime = 0f;
                gameObject.SetActive(false);
                enabled = false;
            }
        }
    }
}
